<template>
    <div class="dj-form-item">
        <div class="label" :class="{'required-start':isRequired}" v-if="label">{{label}}:</div>
        <div class="form-box">
            <slot></slot>
        </div>
        <div class="errorMsg" v-if="validateState=='error'">{{errorMsg}}</div>
    </div>
</template>
<script>
import emitter from '@/mixins/emitter.js'
import AsyncValidator from 'async-validator'
export default {
  name: 'dj-form-item',
  mixins: [emitter],
  inject: ['form'],
  data () {
    return {
      isRequired: false, // 是否为必填
      validateState: '', // 校验状态
      errorMsg: '', // 校验不通过 提示
      initialValue: ''// 存储初始值字段
    }
  },
  props: {
    label: {
      type: String
    },
    prop: {
      type: String
    }
  },
  computed: {
    fieldValue () {
      return this.form.model[this.prop]
    }
  },
  mounted () {
    // 如果没有传入prop则无需校验
    if (this.prop) {
      this.dispatch('dj-form', 'form-item-add', this)
      this.initialValue = this.fieldValue
      this.setRules()
    }
  },
  // 组件销毁前，将实例从 Form 的缓存中移除
  beforeDestroy () {
    this.dispatch('dj-form', 'form-item-remove', this)
  },
  methods: {
    //   触发校验
    setRules () {
      let rules = this.getRules()
      if (rules.length) {
        this.isRequired = rules.some(rule => rule.required)
      }
      this.$on('form-blur', this.onFieldBlur)
      this.$on('form-change', this.onFieldChange)
    },
    // 获取校验规则
    getRules () {
      let rules = this.form.rules
      rules = rules ? rules[this.prop] : []
      return [].concat(rules || [])
    },
    // 只支持blur 和 change 所以过滤掉其他规则
    filterRule (trigger) {
      let currentRule = this.getRules()
      return currentRule.filter(item => !item.trigger || item.trigger.includes(trigger))
    },
    onFieldBlur (val) {
      this.validate('blur')
    },
    onFieldChange (val) {
      this.validate('change')
    },
    // 重置表单初始值
    resetField () {
      this.validateState = ''
      this.errorMsg = ''
      this.form.model[this.prop] = this.initialValue
    },
    // 数据校验
    validate (trigger, callback = () => {}) {
      let rules = this.filterRule(trigger)
      if (!rules || rules.length === 0) {
        return true
      }
      this.validateState = 'validating'
      //   async-validator 校验
      let tem = {}
      let model = {}
      tem[this.prop] = rules
      model[this.prop] = this.fieldValue
      const validator = new AsyncValidator(tem)
      validator.validate(model, { firstFields: true }, error => {
        this.validateState = !error ? 'success' : 'error'
        this.errorMsg = error ? error[0].message : ''
        callback(this.errorMsg)
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.dj-form-item{
    position: relative;
    margin-bottom: 10px;
    padding-bottom: 22px;
    .label{
        min-width: 200px;
        text-align: left;
        margin-bottom: 10px;
        font-weight: bold;
        &::before{
          content: '*';
          display: inline-block;
          color: red;
          margin-right: 10px;
          opacity: 0;
        }
         &.required-start{
            &::before{
              opacity: 1;
            }
          }
    }
    .form-box{
        display: block;
    }
    .errorMsg{
        position: absolute;
        left: 0;
        bottom:0px;
        color: red;
        font-size: 13px;
    }
}
</style>
